Android 源码 Camera2 预览流程分析一

您所在的位置:网站首页 surface 包装 Android 源码 Camera2 预览流程分析一

Android 源码 Camera2 预览流程分析一

2023-10-28 04:00| 来源: 网络整理| 查看: 265

先上一段典型的预览代码,梳理一下相机预览流程。

从 TextureView 获取到 SurfaceTexture 将 SurfaceTexture 默认缓冲区的大小配置为相机预览的大小 新建一个 Surface 作为预览输出 CaptureRequest.Builder 设置 Surface 创建 CameraCaptureSession 用于相机预览 创建成功 CameraCaptureSession 后给 CaptureRequest.Builder 设置自动对焦,必要时开启闪光灯 现在可以开始显示相机预览了,CameraCaptureSession 设置重复请求预览数据 /** * Creates a new [CameraCaptureSession] for camera preview. */ private fun createCameraPreviewSession() { try { val texture = textureView.surfaceTexture // We configure the size of default buffer to be the size of camera preview we want. texture.setDefaultBufferSize(previewSize.width, previewSize.height) // This is the output Surface we need to start preview. val surface = Surface(texture) // We set up a CaptureRequest.Builder with the output Surface. previewRequestBuilder = cameraDevice!!.createCaptureRequest( CameraDevice.TEMPLATE_PREVIEW ) previewRequestBuilder.addTarget(surface) // Here, we create a CameraCaptureSession for camera preview. cameraDevice?.createCaptureSession(Arrays.asList(surface), object : CameraCaptureSession.StateCallback() { override fun onConfigured(cameraCaptureSession: CameraCaptureSession) { // The camera is already closed if (cameraDevice == null) return // When the session is ready, we start displaying the preview. captureSession = cameraCaptureSession try { // Auto focus should be continuous for camera preview. previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE) // Flash is automatically enabled when necessary. setAutoFlash(previewRequestBuilder) // Finally, we start displaying the camera preview. previewRequest = previewRequestBuilder.build() captureSession?.setRepeatingRequest(previewRequest, captureCallback, backgroundHandler) } catch (e: CameraAccessException) { Log.e(TAG, e.toString()) } } override fun onConfigureFailed(session: CameraCaptureSession) { activity.showToast("Failed") } }, null) } catch (e: CameraAccessException) { Log.e(TAG, e.toString()) } }

在这里插入图片描述CameraMetadataNative 类代表 Binder 跨进程通信到 camera service 的相机元数据封送的实现。

这里面涉及了一个重点逻辑调用了 mRemoteDevice 变量指向的对象的 createDefaultRequest(…) 方法。templateType = CameraDevice.TEMPLATE_PREVIEW,其值为 1。然后将输出的 CameraMetadataNative 对象作为 CaptureRequest.Builder 入参构造一个 CaptureRequest.Builder 对象返回。

frameworks/base/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java

public class CameraDeviceImpl extends CameraDevice { ...... @Override public CaptureRequest.Builder createCaptureRequest(int templateType) throws CameraAccessException { synchronized(mInterfaceLock) { checkIfCameraClosedOrInError(); CameraMetadataNative templatedRequest = new CameraMetadataNative(); try { mRemoteDevice.createDefaultRequest(templateType, /*out*/templatedRequest); } catch (CameraRuntimeException e) { throw e.asChecked(); } catch (RemoteException e) { // impossible return null; } CaptureRequest.Builder builder = new CaptureRequest.Builder( templatedRequest, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE); return builder; } } ...... }

首先来确定 mRemoteDevice 是哪里赋值的?CameraDeviceImpl 类 setRemoteDevice(…) 方法中又通过调用 CameraBinderDecorator 类 newInstance(…) 方法创建了实现 ICameraDeviceUser 接口的对象。

frameworks/base/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java

public class CameraDeviceImpl extends CameraDevice { ...... public void setRemoteDevice(ICameraDeviceUser remoteDevice) { synchronized(mInterfaceLock) { // TODO: Move from decorator to direct binder-mediated exceptions // If setRemoteFailure already called, do nothing if (mInError) return; mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice); mDeviceHandler.post(mCallOnOpened); mDeviceHandler.post(mCallOnUnconfigured); } } ...... }

CameraBinderDecorator 类静态方法 newInstance(…) 是个泛型方法。实际上其内部实现为调用 Decorator 泛型类的 newInstance(…) 方法。入参除了 T 类型的对象,还有一个 CameraBinderDecoratorListener 对象。

frameworks/base/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java

public class CameraBinderDecorator { ...... static class CameraBinderDecoratorListener implements Decorator.DecoratorListener { @Override public void onBeforeInvocation(Method m, Object[] args) { } @Override public void onAfterInvocation(Method m, Object[] args, Object result) { // int return type => status_t => convert to exception if (m.getReturnType() == Integer.TYPE) { int returnValue = (Integer) result; throwOnError(returnValue); } } @Override public boolean onCatchException(Method m, Object[] args, Throwable t) { if (t instanceof DeadObjectException) { throw new CameraRuntimeException(CAMERA_DISCONNECTED, "Process hosting the camera service has died unexpectedly", t); } else if (t instanceof RemoteException) { throw new UnsupportedOperationException("An unknown RemoteException was thrown" + " which should never happen.", t); } return false; } @Override public void onFinally(Method m, Object[] args) { } } ...... public static T newInstance(T obj) { return Decorator. newInstance(obj, new CameraBinderDecoratorListener()); } }

代码跟到这个位置就很清晰了,这里使用了 Java 的动态代理机制。也就是说最后返回的实现 ICameraDeviceUser 接口的对象实际上是动态代理到 remoteDevice 引用对象的对象。为什么需要绕一个大弯子?使用动态代理机制可以在不改变原有对象实现方法的基础上完成一些额外功能。

frameworks/base/core/java/android/hardware/camera2/utils/Decorator.java

public class Decorator implements InvocationHandler { ...... @SuppressWarnings("unchecked") public static T newInstance(T obj, DecoratorListener listener) { return (T)java.lang.reflect.Proxy.newProxyInstance( obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new Decorator(obj, listener)); } ...... }

继续分析 CameraDeviceImpl 类 setRemoteDevice(…) 何时被调用?如果对 openCamera(…) 流程还有印象,就知道其赋值是在 CameraManager 类 openCameraDeviceUserAsync(…) 方法中。分析可知 mRemoteDevice 对象实际指向一个 ICameraDeviceUser.Stub.Proxy 类型的对象。

现在可以继续分析 createDefaultRequest(…) 方法调用流程了。ICameraDeviceUser.Stub 和 ICameraDeviceUser.Stub.Proxy 是编译 ICameraDeviceUser.aidl 生成的。最终会调用 BpCameraDeviceUser 类 createDefaultRequest(…) 方法。

frameworks/av/camera/camera2/ICameraDeviceUser.cpp

class BpCameraDeviceUser : public BpInterface { public: ...... // 从模板创建请求对象 virtual status_t createDefaultRequest(int templateId, /*out*/ CameraMetadata* request) { Parcel data, reply; data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); data.writeInt32(templateId); remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply); reply.readExceptionCode(); status_t result = reply.readInt32(); CameraMetadata out; if (reply.readInt32() != 0) { out.readFromParcel(&reply); } if (request != NULL) { request->swap(out); } return result; } }

BpCameraDeviceUser 类 createDefaultRequest(…) 方法会调用到 BnCameraDeviceUser 同名方法。

frameworks/av/include/camera/camera2/ICameraDeviceUser.h

class BnCameraDeviceUser: public BnInterface { public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); };

BnCameraDeviceUser::onTransact(…) 接收到 CREATE_DEFAULT_REQUEST 类型的消息,并调用 createDefaultRequest(…) 方法处理,实际是 BnCameraDeviceUser 的子类。

frameworks/av/camera/camera2/ICameraDeviceUser.cpp

status_t BnCameraDeviceUser::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { ...... case CREATE_DEFAULT_REQUEST: { CHECK_INTERFACE(ICameraDeviceUser, data, reply); int templateId = data.readInt32(); CameraMetadata request; status_t ret; ret = createDefaultRequest(templateId, &request); reply->writeNoException(); reply->writeInt32(ret); // out-variables are after exception and return value reply->writeInt32(1); // to mark presence of metadata object request.writeToParcel(const_cast(reply)); return NO_ERROR; } break; ...... } }

下面是继承链。

CameraDeviceClient -> Camera2ClientBase -> CameraDeviceClientBase -> BnCameraDeviceUser

mDevice 是在 Camera2ClientBase 构造器中初始化的。结合 openCamera 流程可知,假设 mDevice 指向 Camera3Device 对象。

frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp

// Create a request object from a template. status_t CameraDeviceClient::createDefaultRequest(int templateId, /*out*/ CameraMetadata* request) { ATRACE_CALL(); ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; Mutex::Autolock icl(mBinderSerializationLock); if (!mDevice.get()) return DEAD_OBJECT; CameraMetadata metadata; if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK && request != NULL) { request->swap(metadata); } return res; }

Camera3Device::createDefaultRequest(…) 方法实际上调用了 camera3_device_t 结构体内 ops 指向的 camera3_device_ops_t 结构体内的 construct_default_request_settings 函数指针(厂家需要实现)。

这个函数指针的接口定义如下:

为标准相机用例创建捕获设置。

设备必须返回配置为满足请求的用例的设置缓冲区,该缓冲区必须是 CAMERA3_TEMPLATE_ * 枚举之一。 必须包括所有请求控制字段。

HAL 保留了此结构的所有权,但是指向该结构的指针必须有效,直到关闭设备为止。 一旦此调用返回缓冲区,框架和 HAL可能不会修改缓冲区。 对于相同模板或其他模板的后续调用,可以返回相同的缓冲区。

性能要求:

这应该是非阻塞调用。 HAL 应该在 1 毫秒内从此调用返回,并且必须在 5 毫秒内从此调用返回。

frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

status_t Camera3Device::createDefaultRequest(int templateId, CameraMetadata *request) { ATRACE_CALL(); ALOGV("%s: for template %d", __FUNCTION__, templateId); Mutex::Autolock il(mInterfaceLock); Mutex::Autolock l(mLock); switch (mStatus) { case STATUS_ERROR: CLOGE("Device has encountered a serious error"); return INVALID_OPERATION; case STATUS_UNINITIALIZED: CLOGE("Device is not initialized!"); return INVALID_OPERATION; case STATUS_UNCONFIGURED: case STATUS_CONFIGURED: case STATUS_ACTIVE: // OK break; default: SET_ERR_L("Unexpected status: %d", mStatus); return INVALID_OPERATION; } if (!mRequestTemplateCache[templateId].isEmpty()) { *request = mRequestTemplateCache[templateId]; return OK; } const camera_metadata_t *rawRequest; ATRACE_BEGIN("camera3->construct_default_request_settings"); rawRequest = mHal3Device->ops->construct_default_request_settings( mHal3Device, templateId); ATRACE_END(); if (rawRequest == NULL) { ALOGI("%s: template %d is not supported on this camera device", __FUNCTION__, templateId); return BAD_VALUE; } *request = rawRequest; mRequestTemplateCache[templateId] = rawRequest; return OK; }

CaptureRequest.Builder 设置 Surface 这一步,在请求的目标列表(HashSet)中添加一个 Surface,当向相机设备发出请求时,添加的 Surface 必须是对 CameraDevice#createCaptureSession 的最新调用中包含的 Surface 之一。

frameworks/base/core/java/android/hardware/camera2/CaptureRequest.java

public final class CaptureRequest extends CameraMetadata


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3